package service

import (
	"archive/zip"
	"bufio"
	"fmt"
	"gin-epg/internal/app/dao"
	"gin-epg/internal/app/entity"
	"gin-epg/internal/app/mapper"
	"gin-epg/internal/app/model"
	"gin-epg/internal/app/param"
	"io"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

// LivetxtToTvbox txt链接转json
func LivetxtToTvbox(url string) map[string]interface{} {
	json := map[string]interface{}{
		"spider": "",
		"lives": []map[string]interface{}{
			{
				"name": "直播",
				"type": 0,
				"url":  url,
				"epg":  "http://epg.example.com/epg/diyp?ch={name}&date={date}",
				"logo": "http://gitee.com/gsls200808/tv-logo/raw/master/{name}.png",
			},
			{
				"group": "redirect",
				"channels": []map[string]interface{}{
					{
						"name": "live",
						"urls": []string{},
					},
				},
				"epg": "https://epg.112114.eu.org/",
			},
		},
		"rules":     []interface{}{},
		"sites":     []interface{}{},
		"parses":    []interface{}{},
		"flags":     []interface{}{},
		"wallpaper": "",
	}
	return json
}

// MergeTxt 合并两个txt文件
func MergeTxt(path1, path2 string) (*os.File, error) {
	// 读取文件内容
	content1, err := os.ReadFile(path1)
	if err != nil {
		return nil, err
	}

	content2, err := os.ReadFile(path2)
	if err != nil {
		return nil, err
	}

	// 解析文件内容到map
	channel1Map := make(map[string]string)
	scanner := bufio.NewScanner(strings.NewReader(string(content1)))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		parts := strings.Split(line, ",")
		if len(parts) == 2 {
			channelName := strings.TrimSpace(parts[0])
			url := strings.TrimSpace(parts[1])
			channel1Map[url] = channelName
		} else {
			fmt.Printf("Skipped line due to incorrect format: %s\n", line)
		}
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	channel2Map := make(map[string]string)
	scanner = bufio.NewScanner(strings.NewReader(string(content2)))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		parts := strings.Split(line, ",")
		if len(parts) == 2 {
			channelName := strings.TrimSpace(parts[0])
			url := strings.TrimSpace(parts[1])
			channel2Map[url] = channelName
		} else {
			fmt.Printf("Skipped line due to incorrect format: %s\n", line)
		}
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	// 合并map
	for url, channelName := range channel2Map {
		if _, exists := channel1Map[url]; !exists {
			channel1Map[url] = channelName
		}
	}

	// 构造结果输出文件
	result := ""
	for url, channelName := range channel1Map {
		result += fmt.Sprintf("%s,%s\n", channelName, url)
	}

	// 生成临时文件路径
	tempDir := os.TempDir()
	if err := os.MkdirAll(tempDir, os.ModePerm); err != nil {
		return nil, err
	}
	txtFilePath := filepath.Join(tempDir, fmt.Sprintf("merge_%d.txt", time.Now().UnixNano()))

	// 写入合并后的内容到临时文件
	if err := os.WriteFile(txtFilePath, []byte(result), 0644); err != nil {
		return nil, err
	}

	// 返回可读流
	return os.Open(txtFilePath)
}

/*
*
获取epgChannel集合
*/
func GetToolMulticastPlatformList(params *param.QueryToolMulticastPlatformParam) (toolMulticastPlatformList []*entity.ToolMulticastPlatform, err error) {
	toolMulticastPlatformList, err = mapper.GetToolMulticastPlatformList(params)
	if err != nil {
		return nil, err
	}
	return toolMulticastPlatformList, nil
}

/*
*
获取epgChannel集合
*/
func GetToolMulticastChannelByPlatformId(params string) (toolMulticastChannelList []*entity.ToolMulticastChannel, err error) {
	toolMulticastChannelList, err = mapper.GetToolMulticastChannelByPlatformId(params)
	if err != nil {
		return nil, err
	}
	return toolMulticastChannelList, nil
}

// getForwardUrl 转发的域名和端口号
func GetForwardUrl(fwDp, mcUrl string) string {
	// 去除可能的 http:// 前缀
	if strings.HasPrefix(fwDp, "http://") {
		fwDp = fwDp[7:]
	}

	// 处理不同的协议
	if strings.HasPrefix(mcUrl, "udp://") {
		ipAddressPort := mcUrl[6:] // 移除 'udp://' 之后的部分
		parts := strings.Split(ipAddressPort, ":")
		if len(parts) == 2 {
			ipAddress, port := parts[0], parts[1]
			return fmt.Sprintf("http://%s/udp/%s:%s", fwDp, ipAddress, port)
		}
	} else if strings.HasPrefix(mcUrl, "rtp://") {
		ipAddressPort := mcUrl[6:] // 移除 'rtp://' 之后的部分
		parts := strings.Split(ipAddressPort, ":")
		if len(parts) == 2 {
			ipAddress, port := parts[0], parts[1]
			return fmt.Sprintf("http://%s/rtp/%s:%s", fwDp, ipAddress, port)
		}
	}

	// 如果不是预期的协议，原样返回
	return mcUrl
}

// zipDirectory 压缩目录
func ZipDirectory(srcDir, zipFilePath string) error {
	zipFile, err := os.Create(zipFilePath)
	if err != nil {
		return err
	}
	defer zipFile.Close()

	zipWriter := zip.NewWriter(zipFile)
	defer zipWriter.Close()

	err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}

		header.Name = strings.TrimPrefix(path, srcDir)
		if info.IsDir() {
			header.Name += "/"
		} else {
			header.Method = zip.Deflate
		}

		writer, err := zipWriter.CreateHeader(header)
		if err != nil {
			return err
		}

		if !info.IsDir() {
			file, err := os.Open(path)
			if err != nil {
				return err
			}
			defer file.Close()

			_, err = io.Copy(writer, file)
			if err != nil {
				return err
			}
		}

		return nil
	})

	return err
}

// getFileSize 获取文件大小
func GetFileSize(filePath string) int64 {
	fileInfo, err := os.Stat(filePath)
	if err != nil {
		return 0
	}
	return fileInfo.Size()
}

// generateM3UWithExtendedAttributes 根据 PlaylistChannel 列表生成带有扩展属性的 M3U 文件
func GenerateM3UWithExtendedAttributes(channels []model.PlaylistChannel) (io.ReadCloser, error) {
	// 批量查询 EpgChannel 和 EpgChannelAlias 表中的所有数据
	allChannels, allAliases, err := getAllExtendedAttributes()
	if err != nil {
		return nil, err
	}

	// 将查询结果存储在 Map 中
	channelMap := make(map[string]*entity.EpgChannel)
	aliasMap := make(map[string]*entity.EpgChannelAlias)

	for _, channel := range allChannels {
		tempChannel := channel
		channelMap[channel.Name] = tempChannel
	}

	for _, alias := range allAliases {
		tempAlias := alias
		aliasMap[alias.Alias] = tempAlias
	}

	var m3uContent strings.Builder
	m3uContent.WriteString("#EXTM3U\n")

	for _, channel := range channels {
		channelName := channel.Name
		url := channel.URL

		// 检查频道名是否以“咪咕”或“4K”开头
		var groupTitle string
		if strings.HasPrefix(channelName, "咪咕") || strings.HasPrefix(channelName, "4K") {
			groupTitle = "咪咕"
		}

		// 从 Map 中获取扩展属性
		extendedAttrs, err := getExtendedAttributes(channelName, channelMap, aliasMap)
		if err != nil {
			// 如果解析扩展属性失败，跳过该属性的设置
			m3uContent.WriteString(fmt.Sprintf("#EXTINF:-1"))
			if groupTitle != "" {
				m3uContent.WriteString(fmt.Sprintf(" group-title=\"%s\"", groupTitle))
			}
			m3uContent.WriteString(fmt.Sprintf(",%s\n", channelName))
			m3uContent.WriteString(fmt.Sprintf("%s\n", url))
			continue
		}

		// 如果扩展属性中没有设置分组名，则使用我们自定义的分组名
		if groupTitle == "" && extendedAttrs.GroupTitle != "" {
			groupTitle = extendedAttrs.GroupTitle
		}

		// 构建带有扩展属性的 M3U 行
		extInf := "#EXTINF:-1"
		if extendedAttrs.TvgID != "" {
			extInf += fmt.Sprintf(" tvg-id=\"%s\"", extendedAttrs.TvgID)
		}
		if extendedAttrs.TvgName != "" {
			extInf += fmt.Sprintf(" tvg-name=\"%s\"", extendedAttrs.TvgName)
		}
		if extendedAttrs.TvgLogo != "" {
			extInf += fmt.Sprintf(" tvg-logo=\"%s\"", extendedAttrs.TvgLogo)
		}
		if groupTitle != "" {
			extInf += fmt.Sprintf(" group-title=\"%s\"", groupTitle)
		}
		extInf += fmt.Sprintf(",%s\n", channelName)

		m3uContent.WriteString(extInf)
		m3uContent.WriteString(fmt.Sprintf("%s\n", url))
	}

	// 生成临时文件路径
	tempFilePath := filepath.Join(os.TempDir(), "temp.m3u")
	if err := os.WriteFile(tempFilePath, []byte(m3uContent.String()), 0644); err != nil {
		return nil, err
	}

	// 返回文件的读取流
	return os.Open(tempFilePath)
}

// getAllExtendedAttributes 批量查询 EpgChannel 和 EpgChannelAlias 表中的所有数据
func getAllExtendedAttributes() ([]*entity.EpgChannel, []*entity.EpgChannelAlias, error) {
	db := dao.SqlSession

	var allChannels []*entity.EpgChannel
	if err := db.Find(&allChannels).Error; err != nil {
		return nil, nil, err
	}

	var allAliases []*entity.EpgChannelAlias
	if err := db.Find(&allAliases).Error; err != nil {
		return nil, nil, err
	}

	return allChannels, allAliases, nil
}

// ExtendedAttributes 扩展属性结构体
type ExtendedAttributes struct {
	TvgID      string
	TvgName    string
	TvgLogo    string
	GroupTitle string
}

// getExtendedAttributes 从数据库中获取扩展属性
func getExtendedAttributes(channelName string, channelMap map[string]*entity.EpgChannel, aliasMap map[string]*entity.EpgChannelAlias) (ExtendedAttributes, error) {
	// 从 Map 中获取扩展属性
	var extendedAttrs ExtendedAttributes
	if channel, ok := channelMap[channelName]; ok {
		extendedAttrs = ExtendedAttributes{
			TvgID:      strconv.Itoa(channel.Id),
			TvgName:    channelName,
			TvgLogo:    channel.Logo,
			GroupTitle: channel.Group,
		}
		return extendedAttrs, nil
	}

	if alias, ok := aliasMap[channelName]; ok {
		if channel, ok := channelMap[alias.Name]; ok {
			tvgID := fmt.Sprintf("%d_%d", channel.Id, alias.Id)
			extendedAttrs = ExtendedAttributes{
				TvgID:      tvgID,
				TvgName:    channelName,
				TvgLogo:    channel.Logo,
				GroupTitle: channel.Group,
			}
			return extendedAttrs, nil
		}
	}

	return ExtendedAttributes{}, fmt.Errorf("channel or alias not found for name: %s", channelName)
}
